# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time :
# @Author :
# @Email :
# @File :
# @Version:
from typing import List, Dict, Union
import xml.etree.ElementTree as EleTree
from tsn_builder_struct.fwd_mode_tbl_structure import FwdModeTbl, FwdModeTblEachNode, FwdModeEntry_union, FwdModeEntry
from lib.tsn_builder_lib import host_to_net
from tsn_builder_linker.reg_addr_parser import RegAddr


def link_fwd_mode_tbl(node: dict,
                 fwd_mode_tbl: FwdModeTbl,
                 reg_addr: RegAddr) -> List[Dict[str, Union[str, List[str]]]]:
    # 找到该节点对应的转发模式表
    node_id = node['src_node']
    tbl_each_node = []
    for tbl in fwd_mode_tbl.tbl_set:
        if tbl.node_id == node_id:
            tbl_each_node = tbl.tbl_each_node
            break

    if not tbl_each_node:
        return []

    dic = []  # 返回值
    i = 0
    for entry in tbl_each_node:
        fwd_mode_entry = entry.fwd_mode_entry
        if fwd_mode_entry is not None:
            value1 = fwd_mode_entry.byte.entry1
            value2 = fwd_mode_entry.byte.entry2
            value1_str = host_to_net(value1)
            value2_str = host_to_net(value2)

            # 计算该转发模式表的地址
            addr = reg_addr.fwd_mode_tbl['addr']
            width = reg_addr.fwd_mode_tbl['width']
            addr = addr + i * width
            addr_str = host_to_net(addr)
            addr_value = {
                'addr': addr_str,
                'value': [value1_str, value2_str]
            }
            dic.append(addr_value)
            i = i + 1
    return dic


def _get_forward_mode_tbl(forward_mode_tbl_xml):
    fwd_node_entry_set = []
    root = EleTree.parse(forward_mode_tbl_xml)
    node_ele_set = root.findall('node')
    for node_ele in node_ele_set:
        node_entry = {}
        node_id = node_ele.findtext('node_id')
        node_entry.update({'node_id': int(node_id)})
        entry_ele_set = node_ele.findall('entry')
        node_entry.update({'entry_set': []})
        for entry_ele in entry_ele_set:
            valid = entry_ele.findtext('valid')
            reserve = entry_ele.findtext('reserve')
            forward_mode = entry_ele.findtext('forward_mode')
            entry = {
                'valid': int(valid),
                'reserve': int(reserve),
                'forward_mode': int(forward_mode)
            }
            node_entry['entry_set'].append(entry)
        fwd_node_entry_set.append(node_entry)
    return fwd_node_entry_set


def _init_fwd_mode_tbl_obj(forward_mode_set):
    fwd_mode_tbl = FwdModeTbl()
    for tbl_each_node in forward_mode_set:
        node_id = tbl_each_node['node_id']
        entry_set = tbl_each_node['entry_set']
        fwd_mode_tbl_each_node = FwdModeTblEachNode(node_id)
        for entry in entry_set:
            fwd_entry_union = FwdModeEntry_union()
            valid = entry['valid']
            fwd_entry_union.bit.valid = valid
            reserve = entry['reserve']
            fwd_entry_union.bit.reserve = reserve
            forward_mode = entry['forward_mode']
            fwd_entry_union.bit.forward_mode = forward_mode

            fwd_mode_entry = FwdModeEntry(fwd_entry_union)
            fwd_mode_tbl_each_node.append_entry(fwd_mode_entry)
        fwd_mode_tbl.append_tbl(fwd_mode_tbl_each_node)
    return fwd_mode_tbl


def read_fwd_mode_tbl(forward_mode_tbl_xml):
    forward_mode_set = _get_forward_mode_tbl(forward_mode_tbl_xml)
    fwd_mode_tbl = _init_fwd_mode_tbl_obj(forward_mode_set)

    return fwd_mode_tbl


def main():
    forward_mode_tbl_xml = '../output_xml/tbl_xml/forward_mode_tbl.xml'
    fwd_mode_tbl = read_fwd_mode_tbl(forward_mode_tbl_xml)


if __name__ == '__main__':
    main()
